package com.cooksys.film_rental.dao.impl;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.cooksys.film_rental.dao.CountryDao;
import com.cooksys.film_rental.model.City;
import com.cooksys.film_rental.model.Country;

@Repository("CountryDao")
@Transactional
public class CountryDaoImpl implements CountryDao {

	@Autowired(required = true)
	private SessionFactory sessionFactory;

	/**
	 * 
	 * @return the current session from the internal {@link SessionFactory}
	 */
	public Session currentSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public Country save(Country country) {
		Session session = currentSession();
		Serializable id = session.save(country);
		return (Country) session.get(Country.class, id);

	}

	@Override
	public void update(Country country) {
		Session session = currentSession();
		session.update(country);

	}

	@Override
	public void delete(Country country) {
		Session session = currentSession();
		session.delete(country);

	}

	@Override
	public Country getCountryByCountryId(Short countryId) {
		Session session = currentSession();

		// returns a record from the Country table as a Country object based
		// on the given countryId, the table's primary key
		String hql = "from Country where countryId = :countryId";
		Query query = session.createQuery(hql);
		query.setShort("countryId", countryId);

		return (Country) query.list().get(0);
	}

	@Override
	public Country getCountryByCity(City city) {
		Session session = currentSession();

		// selects the country object associated with a given city object
		String hql = "select c.country from City c where c = :city";
		Query query = session.createQuery(hql);
		query.setEntity("city", city);

		return (Country) query.list().get(0);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Country> searchCountriesByPartialCountryName(
			String partialCountryName) {
		Session session = currentSession();

		// split the search string into search terms
		String[] countryNameFragments = partialCountryName.split("\\s");

		// 'select' statement of the hql query
		String hql = "from Country c where ";

		// generating the where clause
		for (int i = 0; i < countryNameFragments.length; i++) {

			// for each search term, add a segment of the where clause that
			// checks country column of the COUNTRY table for matches
			hql += "c.country like :countryNameFragment" + i;

			if (i < countryNameFragments.length - 1) {

				// concatenate these where clause segments with an 'or' operator
				hql += " or ";

			}

		}

		Query query = session.createQuery(hql);

		for (int i = 0; i < countryNameFragments.length; i++) {

			// parameterize the query with the search terms
			query.setString("countryNameFragment" + i, "%"
					+ countryNameFragments[i] + "%");

		}

		return query.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Country> getAllCountries() {
		Session session = currentSession();

		String hql = "from Country";

		Query query = session.createQuery(hql);

		return query.list();
	}

	@Override
	public Country getCountryByInfo(String country) {
		Session session = currentSession();
		
		String hql = "from Country c where c.country = :country";
		Query query = session.createQuery(hql);
		query.setString("country", country);
		
		return (Country) query.uniqueResult();
	}

}
